///******************** NG.Respate(C)  **********************************
//* 产品名称: Respate 科技
//* 文件名称: LapNetRaw.h
//* 功能描述: 原始套接字包
//* 程序作者: 雷帕特公司(南宫子萍)
//* 程序版本: V1.1														   
//* 编制日期: 2019/1/29
//* QQ:	2085827949
//**********************************************************************/
#ifndef __LAP_NET_RAW__
#define __LAP_NET_RAW__

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>             // memset,memcpy
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <net/if.h>             //struct ifreq 
#include <linux/if_ether.h>
#include <linux/if_packet.h>    // struct sockaddr_ll


// ipv4
typedef struct netlayer_ipv4
{
    char version : 4;   // 版本 4bit(IPV4: 4)
    char headlen : 4;   // 头部长度 :一个单位为4字节, 最大数15个单位(60 byte)
    char dscp;          // 区分服务() ：
    uint16_t length;    // 总长度   : 指首部和数据之和的长度，单位为字节,不能超过最大传送单元(MTU)

    short ident;        // 标识     : 计数器，用来产生数据报的标识止,只有当同一个数据段被分成不同的IP数据报，其标识才相同
    uint32_t dmf : 3;   // 片标志   : 后两个比特有意义(保留:DF:MF) DF=0时才允许分片  MF:1 后面还有分片 MF:0 最后一个分片
    uint32_t offset : 13;// 片偏移(Fragment offset) : 以8个字节为偏移单位(offset/8)

    uint8_t ttl;        // 生存时间(Time To Live) : 可通过的路由器数(或跳步数),数据报每经过一个路由器，其TTL值减1,如果TTL=0，路由器则丢弃该IP分组
    uint8_t protocol;   // 传输层协议 ()
    uint16_t headCKS;   // 头部校验和 : 只校验数据报的首部，不包括数据部分。不采用CRC检验码,实现对IP分组首部的差错检测,计算校验和时，该字段置全0 .采用反码算数运算求和(和的反码作为首部校验和字段)
   
    in_addr_t src_ip;   // 源IP
    in_addr_t dst_ip;   // 目标IP

    char opfld[40];     // 选项字段:长度可变(1~40byte) ：携带安全、源选路径、时间戳和路由记录等内容，用来支持排错、测量以及安全等措施，内容很丰富
                        // 增加IP数据报的功能，但增加了每一个路由器处理数据报的开销,实际上这些选项很少使用

                        // 填充字段: 长度可变(0~3byte) ：保证首部32位对齐，即保证首部长度是4字节的倍数

    char* data;         // 数据段
} NetLayer_Ipv4;


typedef struct netlayer_arp
{
    /* data */
}NetLayer_ARP;

typedef struct netlayer_rarp
{
    /* data */
}NetLayer_RARP;

typedef struct netlayer_ipv6
{
    /* data */
}NetLayer_Ipv6;








// 2.网络层
typedef union netlayer
{
    NetLayer_Ipv4   ipv4;
    NetLayer_ARP    arp;
    NetLayer_RARP   rarp;
    NetLayer_Ipv6   ipv46;
}NetLayer;














/* 1.链路层
==========================================================================================================
前导码  |    帧前定界符  |    目的MAC地址    |    源MAC地址   |   长度字段    |    数据字段      |  校验字段 |
----------------------------------------------------------------------------------------------------------|
  7B    |       1B      |        (6B)       |       (6B)    |    (2B)       |   (长度可变)     |   (4B)   |
==========================================================================================================
单位:byte
*/

// 通信协议(网络字节序)
enum ProtocolType
{
    NET_TYPE_IPV4   = 0x0800,   //  0x0800:IPV4数据报
    NET_TYPE_ARP    = 0x0806,   //  0x0806:ARP请求/应答
    NET_TYPE_RARP   = 0x0835,   //  0x0835:RARP请求/应答 
    NET_TYPE_IPV6   = 0x86DD,   //  0x0800:IPV6数据报
}; 

typedef struct netRawPackage
{
    char dst_mac[6];    // 目标mac地址
    char src_mac[6];    // 源mac地址
    short type;         // 通信协议(网络字节序)     0x0800:IP数据报    0x0806:ARP请求/应答    0x0835:RARP请求/应答
    union netlayer net; // 网络层( IP ICMP ARP )
    int32_t crc;        // 链路层尾部 CRC校验和(4字节)
}NetRawPack;





// 创建原始套接字
#define Lap_rawSocket()  socket(PF_PACKET,SOCK_RAW,htons(ETH_P_ALL))




















// CRC校验的FCS算法
/*
//CRC校验的FCS算法
 public static ArrayList<Integer> getCRC(ArrayList<Integer> arrayList){
    int[] cc = new int[]{1,0,0,0,0,0,1,1,1};//生成多项式
    //末尾补0
    for (int i = 0; i < 8; i++) {
        arrayList.add(0);
    }
    int tag = 0;
    ArrayList<Integer> resultList = new ArrayList<>(); //结果list
    ArrayList<Integer> tempList = new ArrayList<>(); //余数缓存list
    //循环开始
    while (tag < arrayList.size() - 8){
        ArrayList<Integer> arrayList1 = new ArrayList<>(); //本次运算取出的前9位
        //若有余数，将余数先加入待计算串
        for (int i = 0; i < tempList.size(); i++) {
            arrayList1.add(tempList.get(i));
        }
        tempList.clear();
        //补齐9位
        for (int i = tag + arrayList1.size(); i < tag + cc.length; i++) {
            arrayList1.add(arrayList.get(i));
        }
        //按位异或
        for (int i = 0; i < cc.length;i++){
            int res = arrayList1.get(i)^cc[i];
            if (res == 0 && tempList.size() == 0)//首位0不计入余数
                tag ++;
            else tempList.add(res);
        }
        resultList = tempList;
    }
    //循环结束后，如果余数不足8位，则要在前面补0
    if (resultList.size()<8){
        ArrayList<Integer> temp = new ArrayList<>();
        for (int i = 0; i < resultList.size(); i++) {
            temp.add(resultList.get(i));
        }
        resultList.clear();
        for (int i = 0; i < 8 - temp.size(); i++) {
            resultList.add(0);
        }
        for (int i = 0; i < temp.size(); i++) {
            resultList.add(temp.get(i));
        }
    }
    return  resultList;//最终的FCS校验码
 }
*/

#endif







																						 
